package com.yh.base.interceptor;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;

import com.yh.base.common.Constant;
import com.yh.base.util.StringUtil;


@Intercepts( {@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})})
public class SqlInterceptor implements Interceptor {
    private final static Log log = LogFactory.getLog(SqlInterceptor.class);

    public Object intercept(Invocation invocation) throws Throwable {
        HttpServletRequest request = getRequest();
        if(request != null) {
            StatementHandler statement = (StatementHandler) invocation.getTarget();
            BoundSql boundSql = statement.getBoundSql();
            String sql = boundSql.getSql();
    /**     // SQL分页查询已经在BaseService中实现，故此处替换不再使用
            PreparedStatementHandler handler = (PreparedStatementHandler) ReflectUtil.getFieldValue(statement, "delegate");
            RowBounds rowBounds = (RowBounds) ReflectUtil.getFieldValue(handler, "rowBounds");
    
            // 设置了分页参数的时候，追加分页条件
            if (rowBounds.getLimit() > 0 && rowBounds.getLimit() < RowBounds.NO_ROW_LIMIT) {
    
                int end_row_num = rowBounds.getLimit() * rowBounds.getOffset();
                int start_row_num = rowBounds.getLimit() * (rowBounds.getOffset() - 1);
    
                // 添加分页参数
                sql = "select * from (select PAGE_TABLE_OTHER_NAME.*, rownum rn from (" + sql + ") PAGE_TABLE_OTHER_NAME where rownum <= " + end_row_num + ") where  rn > " + start_row_num;
    
                ReflectUtil.setFieldValue(boundSql, "sql", sql);
            }*/
            setRuntimeSqlToRequest(request, sql);
        }
        return invocation.proceed();
    }

    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    public void setProperties(Properties properties) {
    }
    
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private HttpServletRequest getRequest() {
        try{
            Class c = Class.forName("org.apache.struts2.ServletActionContext");
            Method m = c.getMethod("getRequest", new Class[] {});
            HttpServletRequest request = (HttpServletRequest) m.invoke(c, new Object[] {});
            return request;
        } catch (Exception e) {
            log.warn("mybatis Interceptor error: can't get request...");
            return null;
        }
    }

    private void setRuntimeSqlToRequest(HttpServletRequest request, String sql) throws Throwable {
        try{
            Object obj = request.getAttribute(Constant.CON_REQUEST_RUNTIME_SQL_KEY);
            sql = sql.replaceAll("(\\n\\s*)+", "\\\n");
            if (StringUtil.isValid(obj)) {
                sql = StringUtil.asString(obj) + "\n======================\n" + sql;
                request.setAttribute(Constant.CON_REQUEST_RUNTIME_SQL_KEY, sql);
            } else {
                request.setAttribute(Constant.CON_REQUEST_RUNTIME_SQL_KEY, sql);
            }
        } catch (Exception e) {
            log.warn("mybatis Interceptor error: save sql to request has error...");
        }
    }

}
